package com.xxl.job.executor.service.jobhandler;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.executor.entity.Trc20WalletDO;
import com.xxl.job.executor.enums.GlobalConfEnum;
import com.xxl.job.executor.enums.NumberEnum;
import com.xxl.job.executor.service.IGlobalConfDOService;
import com.xxl.job.executor.service.ITrc20WalletDOService;
import com.xxl.job.executor.service.Trc20Handler;
import com.xxl.job.executor.utils.CommonConstants;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tron.utils.TronUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * XxlJob开发示例（Bean模式）
 *
 * 开发步骤：
 *      1、任务开发：在Spring Bean实例中，开发Job方法；
 *      2、注解配置：为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")"，注解value值对应的是调度中心新建任务的JobHandler属性的值。
 *      3、执行日志：需要通过 "XxlJobHelper.log" 打印执行日志；
 *      4、任务结果：默认任务结果为 "成功" 状态，不需要主动设置；如有诉求，比如设置任务结果为失败，可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果；
 *
 * @author xuxueli 2019-12-11 21:52:51
 */
@Component
public class Trc20TransferXxlJob {
    private static Logger logger = LoggerFactory.getLogger(Trc20TransferXxlJob.class);

    @Resource
    ITrc20WalletDOService trc20WalletDOService;

    @Autowired
    IGlobalConfDOService globalConfDOService;

    /**
     * 1、转账任务（Bean模式）
     */
    @XxlJob("trc20TransferJobHandler")
    public void trc20TransferJobHandler() throws Exception {
        XxlJobHelper.log("Trc20TransferXxlJob, 开始处理");
        String valueByKey = globalConfDOService.getValueByKey(GlobalConfEnum.IS_AUTO_TRANSFER, NumberEnum.NUMBER_1.getStringValue());
        if (!StringUtils.equals(NumberEnum.NUMBER_1.getStringValue(), valueByKey)) {
            return;
        }

        EntityWrapper<Trc20WalletDO> wrapper = new EntityWrapper<Trc20WalletDO>();
        wrapper.eq("state", NumberEnum.NUMBER_1.getValue());
        String tranferStart = globalConfDOService.getValueByKey(GlobalConfEnum.TRANSFER_START, CommonConstants.TRANFER_DEFAULT_START);
        wrapper.ge("balance", new BigDecimal(tranferStart));
        List<Trc20WalletDO> trc20WalletDOList = trc20WalletDOService.selectList(wrapper);
        trc20WalletDOList.stream().forEach(x->{
            String fromAddress = x.getAddress();
            String privateKey = x.getPrivateKey();
//            if (StringUtils.isBlank(privateKey)) {
//                return;
//            }
//            if (StringUtils.isBlank(fromAddress)) {
//                fromAddress = TronUtils.getAddressByPrivateKey(privateKey);
//                if (StringUtils.isBlank(fromAddress)) {
//                    return;
//                }
//            }
//            BigDecimal balanceUsdt = new Trc20Handler().balanceOfTrc20(fromAddress);
//            if (balanceUsdt.compareTo(new BigDecimal(tranferStart))<0) {
//                return;
//            }
            BigDecimal balanceUsdt = x.getBalance();
            String toAddress = globalConfDOService.getValueByKey(GlobalConfEnum.TRANSFER_TO_ADDRESS, CommonConstants.DEFAULT_TO_ADDRESS);
            try {
                new Trc20Handler().sendTrc20(toAddress, balanceUsdt, privateKey);
            } catch (Throwable e) {
                logger.error(String.format("转账失败|%s", e.getMessage()));
            }
            logger.info(String.format("转账成功|from:%s|amount:%s|to:%s", x.getAddress(), balanceUsdt.doubleValue(), toAddress));
        });
    }

    /**
     * 2、更新地址任务示例（Bean模式）
     */
    @XxlJob("trc20UpdateAddressJobHandler")
    public void trc20UpdateAddressJobHandler() throws Exception {
        XxlJobHelper.log("trc20UpdateAddressJobHandler, 开始处理");

        EntityWrapper<Trc20WalletDO> wrapper = new EntityWrapper<Trc20WalletDO>();
        wrapper.eq("state", NumberEnum.NUMBER_1.getValue());
        List<Trc20WalletDO> trc20WalletDOList = trc20WalletDOService.selectList(wrapper);
        List<Trc20WalletDO> needUpdateList = trc20WalletDOList.stream().filter(x -> StringUtils.isBlank(x.getAddress())).collect(Collectors.toList());
        for (Trc20WalletDO trc20WalletDO : needUpdateList) {
            String address = TronUtils.getAddressByPrivateKey(trc20WalletDO.getPrivateKey());
            trc20WalletDO.setAddress(address);
        }
        if (CollectionUtils.isEmpty(needUpdateList)) {
            return;
        }
        trc20WalletDOService.updateBatchById(needUpdateList);
    }

    /**
     * 3、更新余额任务（Bean模式）
     */
    @XxlJob("trc20UpdateBalanceJobHandler")
    public void trc20UpdateBalanceJobHandler() throws Exception {
        XxlJobHelper.log("trc20UpdateBalanceJobHandler, 开始处理");

        EntityWrapper<Trc20WalletDO> wrapper = new EntityWrapper<Trc20WalletDO>();
        wrapper.eq("state", NumberEnum.NUMBER_1.getValue());
        List<Trc20WalletDO> trc20WalletDOList = trc20WalletDOService.selectList(wrapper);
        List<Trc20WalletDO> needUpdateList = trc20WalletDOList.stream().filter(x -> {
            if (StringUtils.isBlank(x.getAddress())) {
                return false;
            }
            BigDecimal balanceUsdt = new Trc20Handler().balanceOfTrc20(x.getAddress());
            try {
                String sleepTime = globalConfDOService.getValueByKey(GlobalConfEnum.QUERY_BALANCE_SLEEP_TIME, NumberEnum.NUMBER_100.getStringValue());
                TimeUnit.MILLISECONDS.sleep(Integer.valueOf(sleepTime));
            } catch (InterruptedException e) {

            }
            if (balanceUsdt == null) {
                return false;
            }
            if (balanceUsdt.compareTo(x.getBalance()) > 0) {
                x.setBalance(balanceUsdt);
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(needUpdateList)) {
            return;
        }
        trc20WalletDOService.updateBatchById(needUpdateList);
    }

}
